#!/usr/bin/env bash

#################################################
#### Ensure we are in the right path. ###########
#################################################
if [[ 0 -eq $(echo $0 | grep -c '^/') ]]; then
    # relative path
    EXEC_PATH=$(dirname "`pwd`/$0")
else
    # absolute path
    EXEC_PATH=$(dirname "$0")
fi

EXEC_PATH=$(echo ${EXEC_PATH} | sed 's@/\./@/@g' | sed 's@/\.*$@@')
cd $EXEC_PATH || die "$0 Line $LINENO"
#################################################

source "../utils.sh"

TOOLS_DIR=$(dirname ${EXEC_PATH})
ROOT_DIR=$(dirname ${TOOLS_DIR})

DEFAULT_SERV="http://localhost:8545"
SERV=${DZK_BENCH_SERV}
if [[ "" == $SERV ]]; then
    SERV="${DEFAULT_SERV}"
fi

cnt=$1
addr_file="/tmp/dzk_bench.addr.list"
phrase_file="/tmp/dzk_bench.phrase.list"
sender_phrase_file="/tmp/dzk_bench.sender_phrase.list"

root_phrase="$(cat static/root.phrase)"

rounds=

function check_cnt() {
    x=$[$cnt + 1]
    if [[ 0 != $? ]]; then
        die "The number of accounts is not an integer!"
    fi

    if [[ 0 -eq $cnt ]]; then
        die "The nubmer of accounts should not be zero!"
    fi

    rounds=0
    local cnter=$cnt
    let cnter/=10
    while [[ 0 -lt $cnter ]]; do
        let rounds+=1
        let cnter/=10
    done
}

function gen_accounts() {
    rm -rf $addr_file $phrase_file $sender_phrase_file 2>/dev/null
    tmpfile="/tmp/.${RANDOM}.${RANDOM}.${RANDOM}"
    dzk cli gen -n ${cnt} >${tmpfile} || die "$0 Line $LINENO"
    awk 'NR%2==1 {print $0}' ${tmpfile} | grep -o '0x.*' > ${addr_file}
    awk 'NR%2==0 {print $0}' ${tmpfile} | grep 'Phrase' | sed -r 's/^[^ ]+ //g' > ${phrase_file}
    rm $tmpfile || die "$0 Line $LINENO"
    cnt1=$(cat ${phrase_file} | wc -l)
    cnt2=$(cat ${addr_file} | wc -l)
    if [[ $cnt -ne $cnt1 || $cnt1 -ne $cnt2 ]]; then
        die "Fatal: the generated accounts are invalid !"
    fi
}

function run_range() {
    local i=
    local j=
    local k=

    local lower=$1
    local upper=$2
    local amount=$3
    local contract=$4

    local phrase_set=()
    local new_phrase_set=()
    local target_addr_set=()

    IFS_OLD=$IFS
    IFS=$'\n'

    i=0
    for phrase in $(awk '{print $0}' ${sender_phrase_file}); do
        phrase_set[${i}]="${phrase}"
        let i+=1
    done

    i=0
    for phrase in $(awk "NR>=${lower} && NR<=${upper} {print \$0}" ${phrase_file}); do
        new_phrase_set[${i}]="${phrase}"
        let i+=1
    done

    i=0
    for addr in $(awk "NR>=${lower} && NR<=${upper} {print \$0}" ${addr_file}); do
        target_addr_set[${i}]="${addr}"
        let i+=1
    done

    dbg "Length of 'phrase_set': ${#phrase_set[@]}"
    dbg "Length of 'new_phrase_set': ${#new_phrase_set[@]}"
    dbg "Length of 'target_addr_set': ${#target_addr_set[@]}"

    j=
    for ((k=0;k<9;k++)); do
        local batch_txs_start="["
        local batch_txs_end="]"
        for((j=0;j<${#phrase_set[*]};j++));do
            local phrase="${phrase_set[${j}]}"
            local addr_idx=$[9 * ${j} + ${k}]
            local addr=${target_addr_set[${addr_idx}]}
            batch_txs_start="${batch_txs_start}[\"${root_phrase}\",\"${addr}\",\"${amount}\"],"
        done
        batch_txs_start="$(echo ${batch_txs_start} | sed 's/,$//')"
        local batch_txs="${batch_txs_start}${batch_txs_end}"
        local tmpfile="/tmp/.${RANDOM}.${RANDOM}.${RANDOM}"
        echo ${batch_txs} > $tmpfile || die "$0 Line $LINENO"
        if [[ "" == ${contract} ]]; then
            dzk cli transfer -x "${SERV}" -b -f $tmpfile || die "$0 Line $LINENO"
        else
            dzk cli transfer -x "${SERV}" -b -f $tmpfile -C $contract || die "$0 Line $LINENO"
        fi
        rm $tmpfile || die "$0 Line $LINENO"
    done

    printf "" >${sender_phrase_file} || die "$0 Line $LINENO"
    for ((i=0;i<${#new_phrase_set[@]};i++)); do
        echo "${new_phrase_set[${i}]}" >> ${sender_phrase_file} || die "$0 Line $LINENO"
    done

    IFS=$IFS_OLD
}

function run() {
    local i=
    local j=
    local k=

    contract=$1

    local am=10
    for ((k=0;k<${rounds};k++)); do
        let am*=10
    done

    dbg "Total rounds: ${rounds}"
    dbg "Initial amount: ${am}"

    local last_u=0
    local l=$[${last_u} + 1] # awk: index from 1
    local u=
    local size=1
    for ((i=1;i<=${rounds};i++)); do
        let size*=9;
        u=$[${last_u} + ${size}]

        dbg "# Index from 1 # LowerBound(Include): $l, UpperBound(Include): $u"
        dbg "Amount of this round: ${am}, Contract: ${contract}"
        (run_range $l $u ${am} ${contract})

        let am/=10
        last_u=$u
        l=$[${last_u} + 1]
    done
}

check_cnt
gen_accounts

if [[ ${SERV} == ${DEFAULT_SERV} ]]; then
    make -C ${ROOT_DIR} localnet_run || die "$0 Line $LINENO"
    export SERV=$(dzk dev -i \
        | grep 'web3_http' \
        | sed '1d' \
        | grep -o ' [0-9]\+' \
        | sed 's/ /:/' \
        | sed 's@:@http://localhost:@' \
        | tr '\n' ',' \
        | sed 's/,$//' \
    )
    log "RPC Server endpoints: ${SERV}"
fi

log "Waiting RPC-server, sleep 8 seconds"
sleep 8

log "\n\nTransfering native token...\n\n"
cat static/root.phrase > ${sender_phrase_file} || die "$0 Line $LINENO"
run
